package com.liyuhan.onlinetaxibackground.Service.impl;

import com.google.gson.Gson;
import com.liyuhan.onlinetaxibackground.POJO.*;
import com.liyuhan.onlinetaxibackground.Repository.*;
import com.liyuhan.onlinetaxibackground.Service.OrderService;
import com.liyuhan.onlinetaxibackground.Util.DistanceUtil;
import com.liyuhan.onlinetaxibackground.Util.GetRequestBody;
import com.liyuhan.onlinetaxibackground.Util.TimeUtil;
import com.liyuhan.onlinetaxibackground.dto.DataRequest;
import com.liyuhan.onlinetaxibackground.dto.DataResponse;
import com.liyuhan.onlinetaxibackground.dto.orderDto.CompletedOrderDto;
import com.liyuhan.onlinetaxibackground.dto.orderDto.OrderDTO;
import com.liyuhan.onlinetaxibackground.dto.orderDto.ReceivedOrderDto;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.awt.geom.Point2D;
import java.text.DecimalFormat;
import java.util.*;

@Service
public class OrderImpl implements OrderService {

    @Autowired
    private UserRepository userRepository;

    @Autowired
    private PassengerRepository passengerRepository;

    @Autowired
    private BasicOrderRepository basicOrderRepository;

    @Autowired
    private DriverRepository driverRepository;

    @Autowired
    private ReceivedOrderRepository receivedOrderRepository;

    @Autowired
    private CompletedOrderRepository completedOrderRepository;

    @Autowired
    private OrderBlackListRepository orderBlackListRepository;

    // 响应体参数
    private Map<String, String> map;

    // 司机距离乘客的公里数
    private String distance;

    // 用户下单（需要返回订单的id）
    @Override
    public DataResponse doOrder(String request) {
        // 解析请求体
        DataRequest requestBody = GetRequestBody.getRequestBody(request);

        // 获取参数
        // TODO 优化，将phone放到redis中，可以减少数据库查询
        String phone = requestBody.getString("phone");
        Double longitude = Double.valueOf(requestBody.getData().get("longitude").toString());
        Double latitude = Double.valueOf(requestBody.getData().get("latitude").toString());
        String startInfo = requestBody.getString("startInfo");
        String startCity = requestBody.getString("startCity");
        String endInfo = requestBody.getString("endInfo");
        String endCity = requestBody.getString("endCity");
        Integer time = Integer.valueOf(requestBody.getData().get("time").toString());
        Double distance = Double.valueOf(requestBody.getData().get("distance").toString());
        Double cost = Double.valueOf(requestBody.getData().get("cost").toString());
        // 用车时间
        Date useCarDate = TimeUtil.StringToDate(requestBody.getData().get("useCarTime").toString());
        // 订单创建时间（减去三秒，避免报错）
        Date createDate = TimeUtil.TimeStampToDate(new Date().getTime() - 3000L);

        // 订单类型
        String orderType = "";

        // 判断用户叫车类型
        if (TimeUtil.getDateDifference(createDate, useCarDate) == -1) {
            // 用户输入的两个时间有问题
            map = new HashMap<>();

            map.put("error", "您的预约乘车时间不能晚于当前时间!");

            return new DataResponse("700", map);
        } else if (TimeUtil.getDateDifference(createDate, useCarDate) >= 0 &&
                TimeUtil.getDateDifference(createDate, useCarDate) <= 30) {
            orderType = "实时单";
        } else if (TimeUtil.getDateDifference(createDate, useCarDate) > 30) {
            // 与当前时间相差30分钟则为预约单
            orderType = "预约单";
        }

        Passenger passenger = passengerRepository.findPassengerByUser(userRepository.findUserByPhone(phone).get()).get();

        // 创建order对象
        // 订单状态为派单
        // 订单提交时间为现在
        // 订单绑定的乘客使用phone获取
        BasicOrder order = new BasicOrder(longitude, latitude,
                startInfo, startCity,
                endInfo, endCity,
                "0",
                time, distance, cost,
                createDate,
                useCarDate,
                orderType,
                passenger
        );

        // 保存order对象
        basicOrderRepository.save(order);

        // 返回订单号
        map = new HashMap<>();
        map.put("orderId", order.getId().toString());

        return new DataResponse("200", map);
    }

    // 根据用户传入的订单id，获取订单状态
    @Override
    public DataResponse getOrderState(String request) {
        DataRequest requestBody = GetRequestBody.getRequestBody(request);

        Integer orderId = Integer.valueOf(requestBody.getData().get("orderId").toString());

        // 根据id获取订单
        BasicOrder order = basicOrderRepository.findById(orderId).get();

        map = new HashMap<>();
        map.put("state", order.getState());

        // 将订单状态回传
        return new DataResponse("200", map);
    }

    // 根据用户传入的订单id，撤销订单
    @Override
    public void cancelOrder(String request) {
        DataRequest requestBody = GetRequestBody.getRequestBody(request);

        Integer orderId = Integer.valueOf(requestBody.getData().get("orderId").toString());

        // 获取订单
        BasicOrder order = basicOrderRepository.findById(orderId).get();

        // 设置订单状态为“撤销”
        order.setState("1");

        // 更新订单状态
        basicOrderRepository.save(order);
    }

    @Override
    public DataResponse getOrderList(String request) {
        DataRequest requestBody = GetRequestBody.getRequestBody(request);

        map = new HashMap<>();

        String phone = requestBody.getData().get("phone").toString();
        User user = userRepository.findUserByPhone(phone).get();

        if (user.getType().equals("passenger")) {
            Passenger passenger = passengerRepository.findPassengerByUser(user).get();

            // 获取订单信息
            List<BasicOrder> basicOrders = basicOrderRepository.findBasicOrdersByPassenger(passenger).get();
            List<ReceivedOrder> receivedOrders = receivedOrderRepository.findReceivedOrderByPassenger(passenger).get();
            List<CompletedOrder> completedOrders = completedOrderRepository.findCompletedOrdersByPassenger(passenger).get();

            // 返回等待接单订单和撤销订单
            if (basicOrders.size() > 0) {
                for (BasicOrder basicOrder : basicOrders) {
                    // 订单没有被接收
                    if (!basicOrder.getState().equals("2")) {
                        // 将basicOrder转化为orderDTO
                        OrderDTO orderDTO = new OrderDTO(
                                basicOrder.getId(),
                                basicOrder.getStartInfo(),
                                basicOrder.getStartCity(),
                                basicOrder.getEndInfo(),
                                basicOrder.getEndCity(),
                                basicOrder.getState(),
                                basicOrder.getTime(),
                                basicOrder.getDistance(),
                                basicOrder.getCost(),
                                basicOrder.getCreateTime(),
                                basicOrder.getUseCarTime(),
                                basicOrder.getUseCarType()
                        );

                        // 将orderDTO转化为GSON字符串
                        Gson gson = new Gson();
                        String orderStr = gson.toJson(orderDTO);

                        // 将字符串放入map
                        map.put(orderDTO.getId().toString(), orderStr);
                    }
                }
            }
            // 返回正在进行的订单
            if (receivedOrders.size() > 0) {
                for (ReceivedOrder receivedOrder : receivedOrders) {
                    // 订单没有被接收
                    if (!receivedOrder.getState().equals("6")) {
                        // 返回司机前往订单和正在送客订单
                        // 获取司机信息
                        Driver driver = receivedOrder.getDriver();
                        Car car = driver.getCar();
                        // 将basicOrder转化为orderDTO
                        ReceivedOrderDto receivedOrderDto = new ReceivedOrderDto(
                                receivedOrder.getId(),
                                receivedOrder.getOrder(),
                                receivedOrder.getState(),
                                driver.getCity(),
                                driver.getAddress(),
                                driver.getUser().getScore(),
                                car.getCarBrand(),
                                car.getCarColor(),
                                car.getCarNumber(),
                                receivedOrder.getPickUpTime(),
                                receivedOrder.getCancelOrder(),
                                receivedOrder.getCancelReason()
                        );

                        // 将orderDTO转化为GSON字符串
                        Gson gson = new Gson();
                        String orderStr = gson.toJson(receivedOrderDto);

                        // 将字符串放入map
                        map.put(receivedOrderDto.getId().toString(), orderStr);
                    }
                }
            }
            // 返回已完成订单
            if (completedOrders.size() > 0) {
                for (CompletedOrder completedOrder : completedOrders) {
                    // 订单没有被接收
                    if (!completedOrder.getState().equals("9")) {
                        // 返回司机前往订单和正在送客订单
                        // 获取接单信息
                        ReceivedOrder receivedOrder = completedOrder.getReceivedOrder();
                        // 将basicOrder转化为orderDTO
                        CompletedOrderDto completedOrderDto = new CompletedOrderDto(
                                completedOrder.getId(),
                                receivedOrder,
                                completedOrder.getState(),
                                completedOrder.getArriveTime()
                        );

                        // 将orderDTO转化为GSON字符串
                        Gson gson = new Gson();
                        String orderStr = gson.toJson(completedOrderDto);

                        // 将字符串放入map
                        map.put(completedOrderDto.getId().toString(), orderStr);
                    }
                }
            }
        } else if (user.getType().equals("driver")) {
            Driver driver = driverRepository.findDriverByUser(user).get();

            // 获取订单信息
            List<ReceivedOrder> receivedOrders = receivedOrderRepository.findReceivedOrderByDriverAndState(driver, "3").get();
            receivedOrders.addAll(receivedOrderRepository.findReceivedOrderByDriverAndState(driver, "4").get());
            List<CompletedOrder> completedOrders = completedOrderRepository.findCompletedOrdersByDriver(driver).get();

            // 返回正在前往接车的订单
            if (receivedOrders.size() > 0) {
                for (ReceivedOrder receivedOrder : receivedOrders) {
                    // 司机正在前往接车或正在送往终点

                    // 获取当前订单
                    Car car = driver.getCar();
                    ReceivedOrderDto receivedOrderDto = new ReceivedOrderDto(
                            receivedOrder.getId(),
                            receivedOrder.getOrder(),
                            receivedOrder.getState(),
                            driver.getCity(),
                            driver.getAddress(),
                            driver.getUser().getScore(),
                            car.getCarBrand(),
                            car.getCarColor(),
                            car.getCarNumber(),
                            receivedOrder.getPickUpTime(),
                            receivedOrder.getCancelOrder(),
                            receivedOrder.getCancelReason()
                    );

                    // 将orderDTO转化为GSON字符串
                    Gson gson = new Gson();
                    String orderStr = gson.toJson(receivedOrderDto);

                    // 将字符串放入map
                    map.put(receivedOrderDto.getId().toString(), orderStr);
                }
            }
            // 返回已完成订单
            if (completedOrders.size() > 0) {
                for (CompletedOrder completedOrder : completedOrders) {
                    // 订单没有被接收
                    if (!completedOrder.getState().equals("9")) {
                        // 返回司机前往订单和正在送客订单
                        // 获取接单信息
                        ReceivedOrder receivedOrder = completedOrder.getReceivedOrder();
                        // 将basicOrder转化为orderDTO
                        CompletedOrderDto completedOrderDto = new CompletedOrderDto(
                                completedOrder.getId(),
                                receivedOrder,
                                completedOrder.getState(),
                                completedOrder.getArriveTime()
                        );

                        // 将orderDTO转化为GSON字符串
                        Gson gson = new Gson();
                        String orderStr = gson.toJson(completedOrderDto);

                        // 将字符串放入map
                        map.put(completedOrderDto.getId().toString(), orderStr);
                    }
                }
            }
        }
        return new DataResponse("200", map);
    }

    @Override
    public DataResponse getBestOrder(String request) {
        // 请求体
        DataRequest requestBody = GetRequestBody.getRequestBody(request);

        // 响应参数
        map = new HashMap<>();

        // 根据司机位置和订单起点位置获取最合适的订单进行派发
        String phone = requestBody.getData().get("phone").toString();

        // 获取司机
        Driver driver = driverRepository.findDriverByUser(userRepository.findUserByPhone(phone).get()).get();

        // 获取最佳订单
        BasicOrder bestOrder = findBestOrder(driver);

        if (bestOrder == null) {
            return new DataResponse("800", null);
        } else if (driver.getState().equals("0")) {
            return new DataResponse("900", null);
        }

        // 配置订单DTO
        OrderDTO orderDTO = new OrderDTO(bestOrder.getId(),
                bestOrder.getStartInfo(),
                bestOrder.getStartCity(),
                bestOrder.getEndInfo(),
                bestOrder.getEndCity(),
                bestOrder.getState(),
                bestOrder.getTime(),
                bestOrder.getDistance(),
                bestOrder.getCost(),
                bestOrder.getCreateTime(),
                bestOrder.getUseCarTime(),
                bestOrder.getUseCarType());

        orderDTO.setDistanceToDriver(distance);

        // 设置返回参数
        Gson gson = new Gson();
        String orderStr = gson.toJson(orderDTO);

        map.put("order", orderStr);

        return new DataResponse("200", map);
    }

    private BasicOrder findBestOrder(Driver driver) {
        // 获取司机坐标
        Point2D driverPoint = new Point2D.Double(driver.getLongitude(), driver.getLatitude());
        // 距离map
        Map<Integer, Double> distanceMap = new HashMap<>();
        // 获取所有待接单的订单列表
        List<BasicOrder> orders = basicOrderRepository.findBasicOrdersByState("0").get();

        // 计算所有订单距离，放在map中（key:订单id,value:距离）
        if (orders.size() == 0) {
            return null;
        } else {
            // 获取距离map
            for (BasicOrder order : orders) {
                if (orderBlackListRepository.findOrderBlackListsByDriverAndOrder(driver, order).isPresent()) {
                    // 如果当前记录存在于数据库，表明该订单被放入黑名单
                } else {
                    Point2D orderPoint = new Point2D.Double(order.getLongitude(), order.getLatitude());
                    // 计算距离
                    double distance = DistanceUtil.getDistance(orderPoint, driverPoint);
                    // 将距离放入map
                    distanceMap.put(order.getId(), distance);
                }
            }
            // 根据得到的距离map，得到最近距离的订单id
            List<Map.Entry<Integer, Double>> list = new ArrayList(distanceMap.entrySet());
            // 按照距离从小到大排序
            Collections.sort(list, (o1, o2) -> (o1.getValue().intValue() - o2.getValue().intValue()));
            if (list.size() > 0) {
                // 获取
                Integer key = list.get(0).getKey();
                // 保存公里数
                DecimalFormat df = new DecimalFormat("#.0");
                distance = df.format(list.get(0).getValue());

                return basicOrderRepository.findById(key).get();
            }

            return null;
        }
    }

    @Override
    public DataResponse changeBestOrder(String request) {
        DataRequest requestBody = GetRequestBody.getRequestBody(request);

        String phone = requestBody.getData().get("phone").toString();
        String orderId = requestBody.getData().get("orderId").toString();

        Driver driver = driverRepository.findDriverByUser(userRepository.findUserByPhone(phone).get()).get();
        BasicOrder order = basicOrderRepository.findById(Integer.valueOf(orderId)).get();

        OrderBlackList orderBlackList = new OrderBlackList(driver, order);

        orderBlackListRepository.save(orderBlackList);

        return new DataResponse("200", null);
    }

    @Override
    public void deleteOrder(String request) {
        DataRequest requestBody = GetRequestBody.getRequestBody(request);

        String orderId = requestBody.getData().get("orderId").toString();

        // 将订单状态改为2，视为删除
        BasicOrder order = basicOrderRepository.findById(Integer.valueOf(orderId)).get();

        if (order.getState().equals("2")) {
            // 删除receivedOrder
            ReceivedOrder receivedOrder = receivedOrderRepository.findByOrder(order).get();
            receivedOrder.setState("6");

            receivedOrderRepository.save(receivedOrder);
        } else { // 此时order状态一个为1，表示没有接单
            // 删除order
            order.setState("2");

            basicOrderRepository.save(order);
        }
    }

    @Override
    public DataResponse receiveOrder(String request) {
        DataRequest requestBody = GetRequestBody.getRequestBody(request);
        map = new HashMap<>();

        String phone = requestBody.getData().get("phone").toString();
        String orderId = requestBody.getData().get("orderId").toString();

        // 获取订单
        BasicOrder order = basicOrderRepository.findById(Integer.valueOf(orderId)).get();
        // 判断当前订单是否已经被抢走
        if (order.getState().equals("2")) {
            map.put("error", "此订单已被其他司机抢走，请重新接单！");

            return new DataResponse("401", map);
        } else if (order.getState().equals("1")) {
            map.put("error", "此订单已被乘客撤销，请重新接单！");

            return new DataResponse("402", map);
        }

        // 修改原订单为已接单
        order.setState("2");
        basicOrderRepository.save(order);

        // 获取司机
        Driver driver = driverRepository.findDriverByUser(userRepository.findUserByPhone(phone).get()).get();
        // 获取用户
        Passenger passenger = order.getPassenger();
        // 获取车辆
        Car car = driver.getCar();

        // 创建receivedOrder
        ReceivedOrder receivedOrder = new ReceivedOrder(
                "3",
                "0",
                "",
                order,
                passenger,
                driver
        );

        // 保存receivedOrder
        receivedOrderRepository.save(receivedOrder);

        ReceivedOrderDto receivedOrderDto = new ReceivedOrderDto(
                receivedOrder.getId(),
                order,
                receivedOrder.getState(),
                driver.getCity(),
                driver.getAddress(),
                driver.getUser().getScore(),
                car.getCarBrand(),
                car.getCarColor(),
                car.getCarNumber(),
                null,
                null,
                null
        );

        // 将orderDTO转化为GSON字符串
        Gson gson = new Gson();
        String orderStr = gson.toJson(receivedOrderDto);

        // 将字符串放入map
        map.put("order", orderStr);

        // 司机接单成功
        return new DataResponse("200", map);
    }

    @Override
    public DataResponse getCurrentOrder(String request) {
        DataRequest requestBody = GetRequestBody.getRequestBody(request);
        map = new HashMap<>();

        Gson gson = new Gson();

        String phone = requestBody.getData().get("phone").toString();

        User user = userRepository.findUserByPhone(phone).get();

        if (user.getType().equals("driver")) {
            // 该用户为司机
            Driver driver = driverRepository.findDriverByUser(user).get();

            // 获取司机的订单情况
            List<ReceivedOrder> receivedOrders = receivedOrderRepository.findReceivedOrderByDriverAndState(driver, "3").get();
            receivedOrders.addAll(receivedOrderRepository.findReceivedOrderByDriverAndState(driver, "4").get());
            if (receivedOrders.size() > 0) {
                // 司机正在进行的订单
                ReceivedOrder receivedOrder = receivedOrders.get(0);
                Driver driver1 = receivedOrder.getDriver();
                Car car = driver1.getCar();
                ReceivedOrderDto receivedOrderDto = new ReceivedOrderDto(
                        receivedOrder.getId(),
                        receivedOrder.getOrder(),
                        receivedOrder.getState(),
                        driver1.getCity(),
                        driver1.getAddress(),
                        driver1.getUser().getScore(),
                        car.getCarBrand(),
                        car.getCarColor(),
                        car.getCarNumber(),
                        receivedOrder.getPickUpTime(),
                        receivedOrder.getCancelOrder(),
                        receivedOrder.getCancelReason()
                );
                map.put("orderId", receivedOrderDto.getReceivedOrderId().toString());
                map.put("order", gson.toJson(receivedOrderDto));
                return new DataResponse("200", map);
            } else {
                return new DataResponse("1000", null);
            }
        } else {
            // 该用户为乘客
            Passenger passenger = passengerRepository.findPassengerByUser(user).get();

            List<BasicOrder> basicOrders = basicOrderRepository.findBasicOrdersByPassengerAndState(passenger, "0").get();
            if (basicOrders.size() > 0) {
                BasicOrder order = basicOrders.get(0);
                map.put("orderId", order.getId().toString());
                map.put("order", gson.toJson(order));
                return new DataResponse("200", map);
            } else {
                // 不存在叫单
                List<ReceivedOrder> receivedOrders = receivedOrderRepository.findReceivedOrderByPassengerAndState(passenger, "3").get();
                receivedOrders.addAll(receivedOrderRepository.findReceivedOrderByPassengerAndState(passenger, "4").get());
                if (receivedOrders.size() > 0) {
                    ReceivedOrder receivedOrder = receivedOrders.get(0);
                    Driver driver = receivedOrder.getDriver();
                    Car car = driver.getCar();
                    ReceivedOrderDto receivedOrderDto = new ReceivedOrderDto(
                            receivedOrder.getId(),
                            receivedOrder.getOrder(),
                            receivedOrder.getState(),
                            driver.getCity(),
                            driver.getAddress(),
                            driver.getUser().getScore(),
                            car.getCarBrand(),
                            car.getCarColor(),
                            car.getCarNumber(),
                            receivedOrder.getPickUpTime(),
                            receivedOrder.getCancelOrder(),
                            receivedOrder.getCancelReason()
                    );
                    map.put("orderId", receivedOrderDto.getReceivedOrderId().toString());
                    map.put("order", gson.toJson(receivedOrderDto));
                    return new DataResponse("200", map);
                } else {
                    // 不存在已被司机接单的单
                    List<CompletedOrder> completedOrders = completedOrderRepository.findCompletedOrdersByPassengerAndState(passenger, "7").get();
                    if (completedOrders.size() > 0) {
                        // 存在未支付订单
                        CompletedOrder completedOrder = completedOrders.get(0);
                        CompletedOrderDto completedOrderDto = new CompletedOrderDto(
                                completedOrder.getId(),
                                completedOrder.getReceivedOrder(),
                                completedOrder.getState(),
                                completedOrder.getArriveTime()
                        );
                        map.put("orderId", completedOrderDto.getCompleteOrderId().toString());
                        map.put("order", gson.toJson(completedOrderDto));
                        return new DataResponse("200", map);
                    } else {
                        return new DataResponse("1000", null);
                    }

                }
            }
        }
    }
}
